﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Text;

namespace Kylin
{
    public class Logger :  SingletonMonobehaviour <Logger>
    {

        public enum FilterType : byte
        {
            Log = 1,
            Warning = 2,
            Error = 4,
            Assert = 8,
            Exception = 16,
            All = 31
        }

        public bool enableSave = true;

        [Serializable]
        public class Logs
        {
            public string content;
            public string stackTrace;
            public LogType type;

            public string dateTime;

            public Logs(string content, string stackTrace, LogType type, string dateTime)
            {
                this.content = content;
                this.stackTrace = stackTrace;
                this.type = type;
                this.dateTime = dateTime;
            }

            public override string ToString()
            {
                StringBuilder builder = new StringBuilder();

                builder.AppendFormat("[{0}] ", dateTime);
                builder.Append(type.ToString());
                builder.Append(content);
                builder.Append("\n");
                builder.Append(stackTrace);
                builder.Append("\n");
                return builder.ToString();

            }
        }

        [Serializable]
        public class LogInfo
        {
            public List<Logs> logInfoList = new List<Logs>();
        }

        LogInfo logs = new LogInfo();

        byte filter = 31;

        public void SetFilter(byte filter)
        {
            this.filter = filter;
        }

        void OnEnable()
        {
            //Subscribe to Log Event
            Application.logMessageReceived += LogCallback;
        }
       
        void LogCallback(string content, string stackTrace, LogType type)
        {
            bool needLog = false;

            if ((LogType.Log == type && (filter & (byte) FilterType.Log) == (int) FilterType.Log) ||
                (LogType.Warning == type && (filter & (byte)FilterType.Warning) == (int)FilterType.Warning) ||
                (LogType.Error == type && (filter & (byte)FilterType.Error) == (int)FilterType.Error) ||
                (LogType.Assert == type && (filter & (byte)FilterType.Assert) == (int)FilterType.Assert) ||
                (LogType.Exception == type && (filter & (byte)FilterType.Exception) == (int)FilterType.Exception))
            {
                needLog = true;
            }

            if (needLog) {
                Logs logInfo = new Logs(content, stackTrace, type, DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz"));
                logs.logInfoList.Add(logInfo);
            }
        }

        void OnDisable()
        {
            Application.logMessageReceived -= LogCallback;
        }

        void OnApplicationFocus(bool hasFocus)
        {
            if (!hasFocus)
            {
                if (enableSave)
                {
                    DataSaver.SaveData(logs, "savelog");
                }
            }
        }

        void OnApplicationPause(bool pauseStatus)
        {
            if (pauseStatus)
            {
                if (enableSave)
                {
                    DataSaver.SaveData(logs, "savelog");
                }
            }
        }

        private class DataSaver
        {
            public static void SaveData(LogInfo logs, string fileName)
            {
                string filePath;
#if UNITY_EDITOR
                filePath = Application.dataPath + "/../" + fileName;
#else
                filePath = Path.Combine(Application.persistentDataPath, fileName);  
#endif
                using (StreamWriter streamWriter = new StreamWriter(filePath))
                {
                    List<Logs> logList = logs.logInfoList;
                    for (int i = 0; i < logList.Count; ++i)
                    {
                        streamWriter.WriteLine(logList[i].ToString());
                    }
                }
            }
        }
    }
}


